﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace GenericConstraints
{
    // КЛЮЧОВЕ СЛОВО WHERE ЗАДАЄ ОБМЕЖЕННЯ НА ТИП !!!

    //1 вказуємо, що T може бути тільки "value type"
    public class MyValueClass<T> where T : struct
    {
        public MyValueClass()
        {
        }
    }

    //2 Т має бути типом посилань
    public class MyClass<T> where T : class
    {
        public MyClass(T v)
        {

        }
    }

    //3 T має обовязково мати конструктор по замовчуванню
    // дане обмеження завжди має йти останнім в спику
    public class CtorConstraint<T> where T : new()
    {
        public CtorConstraint()
        {

        }
    }

    public class Point
    {
    }

    //4. явно вказуємо до якого типу (класу) має відноситися T
    public class SupperClass<T> where T : Point
    {

    }

    //5. Т має реалізовувати інтерфейс ICollection<int>
    public class MyNewClass<T> where T : ICollection<int>
    {
        public MyNewClass()
        {

        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            //1 успішно компілюється оскільки int value type
            MyValueClass<int> a = new MyValueClass<int>();

            //1 MyValueClass<string> b = new MyValueClass<string>();
            //The type 'string' must be a non-nullable value type in order to use it as parameter 'T'
            //in the generic type or method 'GenericConstraints.MyValueClass<T>'

            //2
            MyClass<string> c = new MyClass<string>("CC");

            //3
            CtorConstraint<MyValueClass<int>> e = new CtorConstraint<MyValueClass<int>>();
            // не можемо вказати за тип MyClass, оскільки він не містить конструктора по замовчуванню
            //CtorConstraint<MyClass<string>> d = new CtorConstraint<MyClass<string>>();

            //4
            SupperClass<Point> str = new SupperClass<Point>();

            //5 MyNewClass<string> g = new MyNewClass<string>();
            MyNewClass<List<int>> g = new MyNewClass<List<int>>();
        }
    }
}
